package org.lex.game.sudoku.view;

import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;

import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;

import org.lex.game.sudoku.model.SudokuModel;
import org.lex.game.sudoku.model.SudokuModelListener;

public class DumpDialog extends JDialog implements SudokuModelListener {
	private static final long serialVersionUID = -5448849127447657836L;

	private static enum Format {
		TEXT() {

			@Override
			public String format(SudokuModel model) {
				return model.dump();
			}
		},
		DEBUG() {
			@Override
			public String format(SudokuModel model) {
				return model.toString();
			}
		};

		public abstract String format(SudokuModel model);
	}

	private static final Format DEFAULT_FORMAT = Format.TEXT;

	private JPanel panel;
	private JToolBar toolBar;
	private JToggleButton textButton;
	private JToggleButton debugButton;
	private JScrollPane scrollPane;
	private JTextArea textArea;

	private ButtonGroup formatButtonGroup;
	private final SudokuModel model;

	/**
	 * Create the dialog.
	 */
	public DumpDialog(Window root, SudokuModel model) {
		super(root, "dump", Dialog.ModalityType.MODELESS);
		this.model = model;
		initialize();
		this.model.addListener(this);
		this.refresh();
	}

	@Override
	public void cellChanged(SudokuModel model, Cause cause, int row, int col, int oldValue, int newValue) {
		refresh();
	}

	@Override
	public void modelChanged(SudokuModel model) {
		refresh();
	}

	private void refresh() {
		Format format = Format.valueOf(this.formatButtonGroup.getSelection().getActionCommand());
		String dump = format.format(this.model);
		this.getTextArea().setText(dump);
	}

	private void initialize() {
		// this.setAlwaysOnTop(true);
		this.setSize(240, 300);
		this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
		this.setContentPane(this.getPanel());
		// button group
		this.formatButtonGroup = new ButtonGroup();
		this.formatButtonGroup.add(this.getTextButton());
		this.formatButtonGroup.add(this.getDebugButton());
		for (Enumeration<AbstractButton> e = this.formatButtonGroup.getElements(); e.hasMoreElements();) {
			ButtonModel model = e.nextElement().getModel();
			if (DEFAULT_FORMAT.name().equals(model.getActionCommand())) {
				formatButtonGroup.setSelected(model, true);
			} else {
				formatButtonGroup.setSelected(model, false);
			}
		}
		// closeing
		this.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				dispose();
			}
		});
	}

	public void setVisible(boolean b) {
		super.setVisible(b);
		if (!b) {
			this.model.removeListener(this);
		}
	}

	public void dispose() {
		super.dispose();
		this.model.removeListener(this);
	}

	private JPanel getPanel() {
		if (panel == null) {
			panel = new JPanel();
			panel.setLayout(new BorderLayout(0, 0));
			panel.add(getToolBar(), BorderLayout.NORTH);
			panel.add(getScrollPane(), BorderLayout.CENTER);
		}
		return panel;
	}

	private JToolBar getToolBar() {
		if (toolBar == null) {
			toolBar = new JToolBar();
			toolBar.add(new JLabel("Format: "));
			toolBar.add(getTextButton());
			toolBar.add(getDebugButton());

		}
		return toolBar;
	}

	private JToggleButton getTextButton() {
		if (textButton == null) {
			textButton = new JToggleButton("Text");
			textButton.setActionCommand(Format.TEXT.name());
			textButton.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					refresh();
				}
			});
		}
		return textButton;
	}

	private JToggleButton getDebugButton() {
		if (debugButton == null) {
			debugButton = new JToggleButton("Debug");
			debugButton.setActionCommand(Format.DEBUG.name());
			debugButton.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					refresh();
				}
			});
		}
		return debugButton;
	}

	private JScrollPane getScrollPane() {
		if (scrollPane == null) {
			scrollPane = new JScrollPane();
			scrollPane.setViewportView(getTextArea());
		}
		return scrollPane;
	}

	private JTextArea getTextArea() {
		if (textArea == null) {
			textArea = new JTextArea();
			textArea.setLineWrap(false);
			textArea.setEditable(false);
		}
		return textArea;
	}
}
